package job_types

import (
	"context"
	"fmt"
	"time"

	"gitlab.ctyuncdn.cn/tai/infra/cloud-controller/internal/job_manager"
	"gitlab.ctyuncdn.cn/tai/infra/cloud-controller/pkg/mysql"
)

// BaseJobTypeHandler provides common functionality for all job type handlers
type BaseJobTypeHandler struct {
	jobType             job_manager.JobType
	description         string
	supportedParameters []job_manager.Parameter
	resourceTemplates   []*job_manager.ResourceTemplate
}

// NewBaseJobTypeHandler creates a new base job type handler
func NewBaseJobTypeHandler(jobType job_manager.JobType, description string) *BaseJobTypeHandler {
	return &BaseJobTypeHandler{
		jobType:     jobType,
		description: description,
		supportedParameters: []job_manager.Parameter{
			{
				Name:        "cpu",
				Type:        "string",
				Required:    false,
				Default:     "1",
				Description: "CPU requirements",
				Validation:  "cpu >= 0.1",
			},
			{
				Name:        "memory",
				Type:        "string",
				Required:    false,
				Default:     "1Gi",
				Description: "Memory requirements",
				Validation:  "memory >= 100Mi",
			},
			{
				Name:        "gpu",
				Type:        "string",
				Required:    false,
				Default:     "0",
				Description: "GPU requirements",
				Validation:  "gpu >= 0",
			},
		},
	}
}

// ValidateJob validates a job
func (h *BaseJobTypeHandler) ValidateJob(job *mysql.Job) error {
	if job == nil {
		return fmt.Errorf("job cannot be nil")
	}

	if job.JobID == "" {
		return fmt.Errorf("job_id is required")
	}

	if job.JobType == "" {
		return fmt.Errorf("job_type is required")
	}

	if job.JobType != string(h.jobType) {
		return fmt.Errorf("job type mismatch: expected %s, got %s", h.jobType, job.JobType)
	}

	return nil
}

// ValidateParameters validates job parameters
func (h *BaseJobTypeHandler) ValidateParameters(params map[string]interface{}) error {
	// Base validation - check required parameters
	for _, param := range h.supportedParameters {
		if param.Required {
			if _, exists := params[param.Name]; !exists {
				return fmt.Errorf("required parameter missing: %s", param.Name)
			}
		}
	}

	return nil
}

// CreateResources creates resources for a job
func (h *BaseJobTypeHandler) CreateResources(ctx context.Context, job *mysql.Job) ([]*job_manager.Resource, error) {
	// Base implementation - create a pod resource
	resources := []*job_manager.Resource{
		{
			Type:      "Pod",
			Name:      fmt.Sprintf("job-%s-pod", job.JobID),
			Namespace: "default",
			Spec: map[string]interface{}{
				"containers": []map[string]interface{}{
					{
						"name":  "main",
						"image": "busybox:latest",
						"command": []string{
							"sleep",
							"3600",
						},
						"resources": map[string]interface{}{
							"requests": map[string]interface{}{
								"cpu":    "100m",
								"memory": "128Mi",
							},
							"limits": map[string]interface{}{
								"cpu":    "500m",
								"memory": "512Mi",
							},
						},
					},
				},
			},
			Status: map[string]interface{}{
				"phase": "Pending",
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
	}

	return resources, nil
}

// DeleteResources deletes resources for a job
func (h *BaseJobTypeHandler) DeleteResources(ctx context.Context, job *mysql.Job) error {
	// Base implementation - resources are automatically cleaned up
	return nil
}

// GetResourceTemplates gets resource templates for a job
func (h *BaseJobTypeHandler) GetResourceTemplates(job *mysql.Job) ([]*job_manager.ResourceTemplate, error) {
	templates := []*job_manager.ResourceTemplate{
		{
			Type:        "Pod",
			Name:        "job-pod-template",
			Namespace:   "default",
			Description: "Base pod template for jobs",
			Template: map[string]interface{}{
				"apiVersion": "v1",
				"kind":       "Pod",
				"metadata": map[string]interface{}{
					"labels": map[string]interface{}{
						"job-id":   "{{.JobID}}",
						"job-type": "{{.JobType}}",
					},
				},
				"spec": map[string]interface{}{
					"containers": []map[string]interface{}{
						{
							"name":  "main",
							"image": "{{.Image}}",
							"resources": map[string]interface{}{
								"requests": map[string]interface{}{
									"cpu":    "{{.CPU}}",
									"memory": "{{.Memory}}",
								},
								"limits": map[string]interface{}{
									"cpu":    "{{.CPULimit}}",
									"memory": "{{.MemoryLimit}}",
								},
							},
						},
					},
				},
			},
			Parameters: h.supportedParameters,
		},
	}

	return templates, nil
}

// StartJob starts a job
func (h *BaseJobTypeHandler) StartJob(ctx context.Context, job *mysql.Job) error {
	// Base implementation - job is considered started when resources are created
	return nil
}

// StopJob stops a job
func (h *BaseJobTypeHandler) StopJob(ctx context.Context, job *mysql.Job) error {
	// Base implementation - job is considered stopped when resources are deleted
	return nil
}

// GetJobStatus gets the status of a job
func (h *BaseJobTypeHandler) GetJobStatus(ctx context.Context, job *mysql.Job) (*mysql.JobStatus, error) {
	// Base implementation - return a default status
	status := &mysql.JobStatus{
		JobID:     job.JobID,
		Status:    string(job_manager.JobStateRunning),
		Message:   "Job is running",
		CreatedAt: time.Now(),
	}

	return status, nil
}

// GetJobType gets the job type
func (h *BaseJobTypeHandler) GetJobType() job_manager.JobType {
	return h.jobType
}

// GetDescription gets the description
func (h *BaseJobTypeHandler) GetDescription() string {
	return h.description
}

// GetSupportedParameters gets the supported parameters
func (h *BaseJobTypeHandler) GetSupportedParameters() []job_manager.Parameter {
	return h.supportedParameters
}
